package com.itheima.rpc.netty.handler;

import com.itheima.rpc.data.RpcRequest;
import com.itheima.rpc.data.RpcResponse;
import com.itheima.rpc.spring.SpringBeanFactory;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;

/**
 * @desc
 * @author:ivan.liu
 */
@Slf4j
@ChannelHandler.Sharable
public class RpcRequestHandler extends SimpleChannelInboundHandler<RpcRequest> {
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest) throws Exception {
        //创建响应对象
        RpcResponse rpcResponse = new RpcResponse();
        rpcResponse.setRequestId(rpcRequest.getRequestId());
        try {
            //获取请求数据
            String className = rpcRequest.getClassName();
            String methodName = rpcRequest.getMethodName();
            Object[] parameters = rpcRequest.getParameters();
            Class<?>[] parameterTypes = rpcRequest.getParameterTypes();
            //根据反射调用方法
            Class<?> clazz = Class.forName(className);
            Object bean = SpringBeanFactory.getBean(clazz);
            Method method = clazz.getMethod(methodName, parameterTypes);
            Object result = method.invoke(bean, parameters);
            //封装响应结果
            rpcResponse.setResult(result);
        } catch (Exception e) {
            rpcResponse.setCause(e);
            log.error("反射调用接口时出错，msg={}",e.getMessage());
        } finally {
            //写出响应结果
            channelHandlerContext.channel().writeAndFlush(rpcResponse);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //打印一次
        log.error("服务端出现异常，异常信息：{}",cause.getCause().toString());
        super.exceptionCaught(ctx, cause);
    }
}
